8  RTTI

Durante la compilazione, viene creato un Class object, contenente tutte le informazioni, per ogni classe che costituisce il programma. Gli oggetti di Class relativi alle varie classi che compongono un programma non sono caricati tutti in memoria prima di iniziare l’esecuzione.

Quando al run-time si istanzia una classe, la JVM su cui sta girando il programma, prima verifica se l’oggetto Class corrispondente è caricato. In caso negativo lo carica ricercando il file .class con quel nome.

Il metodo forName() è un metodo statico di Class che serve per ottenere un riferimento a un oggetto Class. Esso prende un oggetto di tipo String contenente il nome testuale della classe di cui si vuole il riferimento e restituisce un riferimento a Class.

Alternativamente, per ottenere un riferimento a un oggetto Class si può anche ricorrere al letterale di classe (esempio: Gum.class).

I vantaggi di questa notazione sono semplicità, efficienza (non si invoca forName) e controllo di esistenza della classe a compile-time.

Il letterale di classe funziona, oltre che con le classi, con gli array, con i tipi primitivi (e.g., boolean.class) e con le interfacce. Per i wrapper dei tipi primitivi c’è anche un campo standard chiamato TYPE.

Un’altra forma di RTTI in Java è ottenuta attraverso l’uso della parola chiave instanceof che indica se un oggetto è istanza di un particolare tipo e restituisce un boolean, utile per evitare le ClassCastException se si ha bisogno di usare il cast. In alternativa, Class mette a disposizione il metodo isInstance che fornisce un modo per invocare dinamicamente l’operatore instanceof:

Class[] petTypes = {Dog.class, Pug.class};

for(int i = 0; i < pets.size(); i++) {
    Object o = pets.get(i);
    if(o instanceof Pet)
    ((Counter)h.get("Pet")).i++;
    if(o instanceof Dog)
    ((Counter)h.get("Dog")).i++;
    if(o instanceof Pug)
    ((Counter)h.get("Pug")).i++;
}

// Equivalentemente

for (int j = 0; j < petTypes.length; ++j) {
    if (petTypes[j].isInstance(o)) {
        String key = petTypes[j].toString();
        ((Counter)h.get(key)).i++;
    }
}

Quando si dispone di un oggetto, si può estrarre il riferimento all’oggetto Class relativo alla sua classe richiamando un metodo che è implementato in Object: getClass( ).